package com.qn.gateway.fingerprint;

import org.owasp.netryx.config.CommonSecurityConfig;
import org.owasp.netryx.model.CommonConfig;
import org.owasp.netryx.model.LimiterConfig;
import org.owasp.netryx.pipeline.NetArmorPipeline;
import org.owasp.netryx.reactor.ReactorNettyProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.netty.NettyServerCustomizer;
import org.springframework.stereotype.Component;
import reactor.netty.http.server.HttpServer;

/**
 * qingniu-cloud user source analysis
 *
 * @Author: TXG
 * @Date: 2024/6/11
 * @Version V0.0.2
 */
@Component
public class NetArmorCustomizer implements NettyServerCustomizer {
    @Autowired
    NetArmorConfig armorConfig;
    @Override
    public HttpServer apply(HttpServer server) {
        if (armorConfig.isFingerprint()==false) {
            return server;
        }
        CommonConfig commonConfig = new CommonConfig();
        //HTTP 速率限制可防止 DoS、暴力攻击等。
        LimiterProperties resetStream = armorConfig.getResetStream();
        commonConfig.setLimitRapidReset(resetStream.isEnabled());
        if (commonConfig.isLimitRapidReset()) {
            commonConfig.setResetStreamLimiter(new LimiterConfig(resetStream.isEnabled(),
                    resetStream.getMaxCount(),
                    resetStream.getCheckIntervalMillis(),
                    resetStream.getBlockTimeSeconds(),
                    resetStream.getCacheFlushMillis()));
        }
        //HTTP/2 0day RST 洪水保护
        resetStream = armorConfig.getRequest();
        commonConfig.setLimitRequests(resetStream.isEnabled());
        if (commonConfig.isLimitRequests()) {
            commonConfig.setRequestLimiter(new LimiterConfig(resetStream.isEnabled(),
                    resetStream.getMaxCount(),
                    resetStream.getCheckIntervalMillis(),
                    resetStream.getBlockTimeSeconds(),
                    resetStream.getCacheFlushMillis()));
        }
        //安全策略管理（CSP、XFO 等）此处合并
        commonConfig.setEnableSecurityPolicy(armorConfig.isSecurityPolicy());
        if (commonConfig.isEnableSecurityPolicy() && armorConfig.getPatterns() != null) {
            armorConfig.getPatterns().forEach((key, value) -> {
                commonConfig.getPatterns().put(key, value);
            });
        }
        CommonSecurityConfig config = new CommonSecurityConfig(commonConfig);
        NetArmorPipeline<HttpServer> armorPipeline = NetArmorPipeline.newBuilder(
                        new ReactorNettyProvider(config))
                .intrusion(new FingerprintIntrusion())
                //此处需要添加配置防止全局不生效
                .config(config)
                .build();
        return armorPipeline.pipeline().configure(server);
    }
}